package com.winit.openapi.upush2.sender;

import java.util.Date;

import javax.annotation.Resource;

import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpStatus;
import org.apache.commons.httpclient.methods.PostMethod;
import org.apache.commons.httpclient.methods.StringRequestEntity;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import com.alibaba.fastjson.JSONObject;
import com.winit.common.spi.SPIException;
import com.winit.common.spi.context.CommandContext;
import com.winit.openapi.constants.ApiConstant;
import com.winit.openapi.constants.ErrorCode;
import com.winit.openapi.util.APISysConfigUtil;
import com.winit.openapi.util.DateUtil;
import com.winit.openapi.util.RedisUtil;
import com.winit.spi.send.SendService;
import com.winit.spi.send.command.SendCommand;

/**
 * upush2.0邮件发送类
 * 
 * @version <pre>
 * Author	Version		Date		Changes
 * minghao.deng 	1.0  		2017年8月30日 	Created
 *
 * </pre>
 * @since 1.
 */
@Service("apiMonitoringEmailSender")
public class APIMonitoringEmailSender {

    private static final Logger logger               = LoggerFactory.getLogger(APIMonitoringEmailSender.class);

    private static final String API_FREQUENCY_PREFIX = "API_frequency_";

    @Resource
    private SendService         sendService;

    @Resource
    private APISysConfigUtil    apiSysConfigUtil;

    /**
     * 发送信息,支持手机和邮件
     */
    public void pushMsg(UPushMessageModel msg) {
        String data = JSONObject.toJSONString(msg);
        if (StringUtils.isBlank(data)) {
            return;
        }
        logger.info("upush推送信息：" + data);
        // 读取发送邮件或短信的服务器地址
        String serverUrl = apiSysConfigUtil.getConfigValueByKey("API_PUSH_MSG_URL");
        if (StringUtils.isBlank(serverUrl)) {
            return;
        }
        postMsgToUpush(serverUrl, data);

    }

    public void sendEmail(JSONObject dataModel) {

        logger.info("API异常调用邮件告警：" + dataModel.toJSONString());

        SendCommand command = new SendCommand();

        command.setTopic("API_FREQUENCY_MONITORING_ERROR");
        command.setGroup("API_FREQUENCY_MONITORING_ERROR");

        command.setDataModel(dataModel);

        sendService.send(command);

    }

    /**
     * API调用异常邮件告警 以账号为维度，在設定的expireTime时间内只发送一次
     * 
     * @param appKey 异常账号
     * @param frequency 异常频率
     * @param ip 异常IP
     */
    public void checkAndSendEmail(String appKey, int frequency, int maxFrequency) {
        // 超时时间，默认半小时
        String expireTime = apiSysConfigUtil.getConfigValueByKey("API_FREQUENCY_WARNNING_INTERVAL");
        String warnInterval = apiSysConfigUtil.getConfigValueByKey("API_FREQUENCY_WARNNING_COUNT");
        int expireTimeInt = StringUtils.isBlank(expireTime) ? 60 * 30 : Integer.valueOf(expireTime);
        long warnIntervalValue = StringUtils.isBlank(warnInterval) ? 5 : Long.valueOf(warnInterval);
        String maxLastUnitKey = API_FREQUENCY_PREFIX + "max_" + appKey;
        String lockFlag = API_FREQUENCY_PREFIX + "lockFlag_" + appKey;

        if (frequency == maxFrequency + 2) {
            // 获取到锁的线程执行发送邮件操作
            Long result = RedisUtil.incr(lockFlag);
            if (result.longValue() == warnIntervalValue) {
                String flag = apiSysConfigUtil.getConfigValueByKey("API_FREQUENCY_WARNNING_NOTICE_FLAG");
                String maxCount = RedisUtil.get(maxLastUnitKey);
                JSONObject jsonInfo = new JSONObject();
                jsonInfo.put("userAccount", appKey);
                CommandContext ctx = CommandContext.getContext();
                jsonInfo.put("IP",
                    ctx.get(ApiConstant.SOURCE_IP) == null ? "127.0.0.1" : ctx.get(ApiConstant.SOURCE_IP));
                jsonInfo.put("frequency", StringUtils.isBlank(maxCount) ? frequency : maxCount);
                jsonInfo.put("time", DateUtil.parse2String(new Date(), DateUtil.FULL_DATE_STRING));
                try {
                    if (Boolean.parseBoolean(flag)) {
                        sendEmail(jsonInfo);
                    }
                } catch (Exception e) {
                    logger.error("发送API异常调用告警失败，内容：" + jsonInfo + "\n 失败原因：" + e);
                }
                RedisUtil.setExpireTime(lockFlag, expireTimeInt);
                RedisUtil.remove(maxLastUnitKey);
            }
        } else {

            String maxLastUnitValue = RedisUtil.get(maxLastUnitKey);
            if (StringUtils.isBlank(maxLastUnitValue)) {
                RedisUtil.put(maxLastUnitKey, String.valueOf(frequency));
            } else {
                int maxLastUnitIntValue = maxFrequency;
                try {
                    maxLastUnitIntValue = Integer.valueOf(maxLastUnitValue);
                } catch (NumberFormatException e) {
                    RedisUtil.put(maxLastUnitKey, String.valueOf(maxFrequency));
                }
                if (maxLastUnitIntValue < frequency) {
                    RedisUtil.put(maxLastUnitKey, String.valueOf(frequency));
                }

            }

        }

    }

    private void postMsgToUpush(String url, String postData) {
        PostMethod post = null;
        try {
            StringRequestEntity entity = new StringRequestEntity(postData,
                ApiConstant.CONTENT_TYPE_JSON,
                ApiConstant.CHARSET_UTF8);

            post = new PostMethod(url);
            post.setRequestEntity(entity);

            HttpClient client = new HttpClient();
            // 设置连接超时时间
            client.getHttpConnectionManager().getParams().setConnectionTimeout(60 * 1000);
            client.getHttpConnectionManager().getParams().setSoTimeout(60 * 1000);
            int statusCode = client.executeMethod(post);

            if (statusCode == HttpStatus.SC_OK || statusCode == HttpStatus.SC_CREATED) {
                IOUtils.toString(post.getResponseBodyAsStream(), ApiConstant.CHARSET_UTF8);
            } else {
                logger.error("推送短信、邮件到upush失败：url: " + url + " data:" + postData + " 返回code：" + statusCode + " 原因："
                             + post.getStatusText());
                throw new SPIException(ErrorCode.OAUTH_PUSH_MSG_ERROR);
            }
        } catch (Exception e) {
            logger.error("推送短信、邮件到upush失败：url: " + url + " data:" + postData + " 原因：" + e);
            throw new SPIException(ErrorCode.OAUTH_PUSH_MSG_ERROR);
        } finally {
            if (post != null) {
                post.releaseConnection();// 会自动释放连接
            }
        }
    }
}
